package com.pesking.core.sqlparser;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.pesking.core.datasource.Page;
import com.pesking.core.parameter.Parameter;
import com.pesking.core.thread.ThreadManage;
import com.pesking.core.util.DateUtils;
import com.pesking.core.util.LogUtils;

/**
 * sql结果类
 * @author chenyunpei
 * @since 2010-10-02
 * @version 1.0
 */
public abstract class SqlResult<T> {

	protected Page page = null;
	protected Parameter requestParameter = null;
	protected T result = null;
	
	public SqlResult(Parameter requestParameter){
		this.requestParameter = requestParameter;
		if (this.requestParameter == null) {
			this.requestParameter = ThreadManage.getCurrentParameter();
		}
	}
	
	public boolean isUpdateResult(){
		return false;
	}
	
	public Page getPage() {
		return page;
	}

	public void setPage(Page page) {
		this.page = page;
	}
	
	/**
	 * 处理更新返回值
	 * @param rtn
	 */
	public void dealUpdateReturnValue(int rtn) {
		
	}
	
	/**
	 * 处理结果集
	 * @param rs
	 */
	public void dealResultSet(ResultSet rs) throws SQLException{
		if (rs == null){
			return;
		}
		Map<?,?> mapColumnName = getColumnName(rs);
		int count = 0;
		int pageSize = 0;
		if (page != null){
			pageSize = page.getPageSize();
		}
		this.result = this.newResult();
		beforeResult(rs);
		while(rs.next()){
			count++;
			if (page != null && count > pageSize){
				continue;
			}
			beforeRecord();
			Iterator<?> it = mapColumnName.keySet().iterator();
			while(it.hasNext()){
				String columnName = (String)it.next();
				ColumnInfo ci = (ColumnInfo)mapColumnName.get(columnName);	
				String value = ci.getValue(rs);
				if (value == null || "null".equals(value))
				{
					value = "";
				}
				else
				{
					value = value.trim();
				}
				columnName = columnName.toUpperCase();
				dealColumn(ci,columnName,value);
			}			
			afterRecord();
			
		}
		if (page != null){
			
			int nextCount = (int)Math.ceil(1.0 * count / pageSize) - 1;
			if (nextCount < 0){
				nextCount = 0;
			}
			if (nextCount > page.getMaxNextCount()){
				nextCount = page.getMaxNextCount();
			}
			LogUtils.debug("此次查询记录数：" + count + "  页大小:" + pageSize + " 本次页后后续页数：" + nextCount);
			page.setNextCount(nextCount);
			
		}
		afterResult();
	}	
	
	protected void beforeResult(ResultSet rs)  throws SQLException{
		
	}
	
	protected void afterResult()  throws SQLException{
		
	}
	
	protected void beforeRecord()  throws SQLException{
		
	}
	
	protected void afterRecord()  throws SQLException{
		
	}
	
	protected abstract T newResult();
	
	protected abstract void dealColumn(ColumnInfo ci,String columnName,String columnValue);
	
	public T getResult() {
		return result;
	}

	protected Map<String,ColumnInfo> getColumnName(ResultSet rs) throws SQLException
	{
		Map<String,ColumnInfo> mapColumnName = new HashMap<>();		
		ResultSetMetaData rsmd = rs.getMetaData();
		if (rsmd != null){
			int count = rsmd.getColumnCount();
			for (int i = 0 ; i < count ; i++)
			{
				String columnName = rsmd.getColumnLabel(i + 1);
				mapColumnName.put(columnName,new ColumnInfo(columnName,rsmd.getColumnType(i + 1)));
			}
		}
		return mapColumnName;
	}
	
	protected static class ColumnInfo{
		/**列的别名*/
		//private String aliasName	= null;
		/** 列类型 */
		public int columnType		= 0;
		/**列名称*/
		public String columnName	= null;
		
		public ColumnInfo(String columnName,int columnType){
			
			this.columnType = columnType;
			this.columnName = columnName;
			if (columnName == null){
				return;
			}
		}
		
		public String getValue(ResultSet rs) throws SQLException{
			String result = null;
			if (this.columnType == java.sql.Types.CLOB){
				LogUtils.error("本系统暂时不处理clob字段，此字段将置为空字符串.");
				result = "";
			}
			else if (this.columnType == Types.DECIMAL) {
				BigDecimal bigDecimal = rs.getBigDecimal(this.columnName);
				if (bigDecimal != null) {
					result = bigDecimal.toPlainString();
				}
			}
			else if (this.columnType == Types.DOUBLE) {
				double dbl = rs.getDouble(this.columnName);
				BigDecimal bigDecimal = new BigDecimal(dbl);
				result = bigDecimal.toPlainString();
			}
			else if (this.columnType == Types.DATALINK){
				Date date = rs.getDate(this.columnName);
				if (date != null){
					result = DateUtils.date2String(date);
				}
				else{
					result = "";
				}
			}
			else if (this.columnType == Types.TIMESTAMP){
				
				Timestamp ts = rs.getTimestamp(this.columnName);
				if (ts != null){
					result = DateUtils.timestamp2String(ts);
				}
				else{
					result = "";
				}
				/*
				result = rs.getString(this.columnName);
				*/
			}
			else{
				result = rs.getString(this.columnName);
			}
			
			if (result == null){
				result = "";
			}
			return result;
		}
		
	}
	
}
